using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using Tools.Maptools.Editor;
using UnityEditor;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Networking;
using WorldMap;
using WorldMapBase;
using WorldMapNew;
using Yoozoo.Managers.ResourceManagerV2.Framework.Resource;
using Yoozoo.Managers.ResourceManagerV2.Runtime;
using Yoozoo.UI.YGUI;

namespace WorldMapTools
{
    [DisallowMultipleComponent]
    public class GeneralMap
    {
        public static GameObject mapObj;

        public string mapName = "MapRoot";
        public int Lod = 0;
        public int Size = 30;
        public int wSize = WorldEntry.m_mapSize / WorldEntry.m_iTileSize;
        public int wOverSeaSize = 138;
        public int hSize = WorldEntry.m_mapSize / WorldEntry.m_iTileSize;
        public int tileWidth = 30;
        public int tileHeight = 30;
        public static string savePath = "Assets/ResourcesAssets/World/mapdata";
        public static string tilesPath = "ResourcesAssets/World/prefabs/sandtable/tiles";
        public static string randomPrefabPath = "ResourcesAssets/World/prefabs/sandtable/trees";

        public static Dictionary<string, int> layer_name_to_id = new Dictionary<string, int>();

        // 初始化 层级 - ID 映射
        public static void InitLayerNameToId()
        {
            if (layer_name_to_id.Count <= 0)
            {
                layer_name_to_id[WorldEntry.PLANE_LAYER_NAME] = WorldEntry.PLANE_LAYER_ID;
                layer_name_to_id[WorldEntry.TREE_LAYER_NAME] = WorldEntry.TREE_LAYER_ID;
                layer_name_to_id[WorldEntry.MOUNTAINRANGE_LAYER_NAME] = WorldEntry.MOUNTAINRANGE_LAYER_ID;
                layer_name_to_id[WorldEntry.MOUNTAIN_LAYER_NAME] = WorldEntry.MOUNTAIN_LAYER_ID;

                layer_name_to_id[WorldEntry.TRAFFIC_LAYER_NAME] = WorldEntry.TRAFFIC_LAYER_ID;
                layer_name_to_id[WorldEntry.DECORATION_LAYER_NAME] = WorldEntry.DECORATION_LAYER_ID;

                layer_name_to_id[WorldEntry.ALLIANCEPOINT_ROAD_LAYER_NAME] = WorldEntry.ALLIANCEPOINT_ROAD_LAYER_ID;
                layer_name_to_id[WorldEntry.ALLIANCEPOINT_CROSS_LAYER_NAME] = WorldEntry.ALLIANCEPOINT_CROSS_LAYER_ID;
                layer_name_to_id[WorldEntry.MAP_POINT_ADORN_LAYER_NAME] = WorldEntry.MAP_POINT_ADORN_LAYER_ID;
            }
        }

        // 初始化 资源路径 -ID 映射
        public static void InportMapPrefabMap()
        {
            if (MapPrefabMap.Count > 0) return;
            MapPrefabMap content = AssetDatabase.LoadAssetAtPath<MapPrefabMap>(MapPrefabMapPath);
            if (content != null)
            {
                for (int i = 0; i < content.mapPrefabMap.Count; i++)
                {
                    PrefabData prefab = content.mapPrefabMap[i];
                    string path = prefab.resPath;
                    int id = prefab.resID;
                    MapPrefabMap[path] = id;
                    MapPrefabMapIdToPath[id] = path;
                    if (id < 1000000)
                    { 
                        MapPrefabMaxId = Mathf.Max(MapPrefabMaxId, id);
                    }
                }
            }
            MapPrefabMaxId++;
        }

        public bool generalMap()
        {
            var t = DateTime.Now;
            var obj = new GameObject(this.mapName);
            mapObj = obj;
            var mapEditorHelperObj = mapObj.AddComponent<MapEditorHelper>();
            mapEditorHelperObj.mapName = this.mapName;
            mapEditorHelperObj.wSize = this.wSize;
            mapEditorHelperObj.hSize = this.hSize;
            mapEditorHelperObj.TILE_WIDTH = this.tileWidth;
            mapEditorHelperObj.TILE_HEIGHT = this.tileHeight;
            mapEditorHelperObj.savePath = savePath;
            mapEditorHelperObj.tilesPath = tilesPath;
            mapEditorHelperObj.Lod = this.Lod;
            mapEditorHelperObj.Size = this.Size;

            return true;
        }

        // ============================== 大地图数据处理 ==============================

        // 导出大地图数据 船新版本 20220831
        public static bool SaveMap(GameObject mapObj)
        {
            if (mapObj)
            {
                InitLayerNameToId();
                InportMapPrefabMap();
                // 检查大地图编辑对象数据
                MapEditorHelper mapEditorHelper = mapObj.GetComponent<MapEditorHelper>();
                if (mapEditorHelper.CheckItem() == false) 
                {
                    // 地图块个数不对
                    return false;
                }
                else
                {
                    // 排序
                    mapEditorHelper.SortTile();
                }
                var result = SaveAsMapScriptObject(mapObj); // 保存数据
                // 导出最新地图映射
                ExportMapPrefabMap();
                return result;
            }
            return false;
        }

        // 保存地图对象(保存的知识某一个lod的数据)
        public static bool SaveAsMapScriptObject(GameObject mapPrefab)
        {
            var mapEditorHelper = mapPrefab.GetComponent<MapEditorHelper>();
            // 1 创建数据
            var mapData = ScriptableObject.CreateInstance<WorldMapData>();
            mapData.mapWidth = mapEditorHelper.wSize * mapEditorHelper.TILE_WIDTH;
            mapData.mapHeight = mapEditorHelper.hSize * mapEditorHelper.TILE_HEIGHT;
            mapData.name = mapPrefab.name;

            // 2 创建lod数据
            MapLODData lodData = new MapLODData() {
                lodDistance = mapEditorHelper.Lod,
                tileSize = mapEditorHelper.TILE_WIDTH,
            };

            // 3 导出所有地图块
            for (int i = 0; i < mapPrefab.transform.childCount; i++)
            {
                Transform transform = mapPrefab.transform.GetChild(i);
                int chunckId = GetMapChunckId(transform);
                lodData.AddMapChunckId(chunckId);
            }
            mapData.AddLODData(lodData);
        
            AssetDatabase.CreateAsset(mapData, mapEditorHelper.savePath + "/" + mapEditorHelper.mapName + "_mapdata.asset");
            return true;
        }

        // 解析出地块资源id
        private static int GetMapChunckId(Transform basePlane)
        {
            int index1 = basePlane.gameObject.name.IndexOf('<');
            int index2 = basePlane.gameObject.name.LastIndexOf('>');
            string objpath = basePlane.gameObject.name.Substring(index1 + 1, index2 - index1 - 1);
            string[] objpaths = objpath.Split('/');
            string path = savePath + "/" + objpaths[objpaths.Count() - 1].Replace(".prefab", "") + "_chuckData.asset";
            int chunckId = GetMapPrefabId(path); // 地图块配置id就是该地块预制体id
            return chunckId;
        }

        // ============================== 地图块数据处理 ==============================

        public static Dictionary<string, int> MapPrefabMap = new Dictionary<string, int>();
        public static Dictionary<int, string> MapPrefabMapIdToPath = new Dictionary<int, string>();
        public static string MapPrefabMapPath = "Assets/ResourcesAssets/World/mapdata/mapPrefabMap.asset";
        string mapPointPrefabPath = "Assets/ResourcesAssets/World/prefabs/sandtable/other/mapPoint.prefab";
        string mapUnionPointPrefabPath = "Assets/ResourcesAssets/World/prefabs/sandtable/other/mapUnion.prefab";
        public static int MapPrefabMaxId = 0;
        // 导出地图块数据 船新版本 20220831
        public bool ExportMapChuckCfg(GameObject mapChuck, Dictionary<GameObject, int> MapChunckLevelMap,bool bExportMapPrefabMap = true)
        {
            if (mapChuck == null) return false;
            // 1 前置配置导入
            InitLayerNameToId();    // 层级名 - 层级ID 映射
            InportMapPrefabMap();   // 地图对象资源路径 -资源唯一ID 映射
            // 2 保存数据信息
            MapChunckData mapChuckCfg = ScriptableObject.CreateInstance<MapChunckData>();
            mapChuckCfg.chunckSize = WorldEntry.m_iTileSize;
            string name = CreateMapEditorWindow.StrReplace(mapChuck.gameObject.name, "_Editor", "");
            int curLod = GetMapChunckLod(name);
            // 3 添加层级数据
            for (int i = 0; i < mapChuck.transform.childCount; i++)
            {
                Transform layer = mapChuck.transform.GetChild(i);
                if (!layer.name.Contains("Layer"))// 防止错误节点
                {
                    EditorUtility.DisplayDialog("错误", "当前导出地图块存在错误层级节点 ：" + layer.name + " chunckNbame : " + mapChuck.name, "ok");
                    continue;
                }
                //if (layer.gameObject.activeSelf == false)// 隐藏节点不导出
                //{
                //    continue;
                //}
                string layername = layer.name;
                layername = layername.Replace(" ", "");
                if (!layer_name_to_id.ContainsKey(layername)) continue;
                int layerID = layer_name_to_id[layername];

                if (layerID == WorldEntry.ALLIANCEPOINT_ROAD_LAYER_ID)
                {
                    AddTileAllianceRoadData(layer, mapChuckCfg); // 添加街区点 二车道
                    continue;
                }
                else if (layerID == WorldEntry.ALLIANCEPOINT_CROSS_LAYER_ID)
                {
                    AddTileAllianceCrossData(layer, mapChuckCfg); // 添加街区点 衔接道路
                    continue;
                }
                else if (layerID == WorldEntry.MAP_POINT_ADORN_LAYER_ID)
                {
                    AddTilePointAdornData(layer, mapChuckCfg); // 添加出生点 装饰物
                    continue;
                }
                MapChunckLayer chuncklayer = new MapChunckLayer
                {
                    layerID = layerID,
                    name = layername,
                    layerSize = WorldEntry.GetLayerSizeByLod(layerID, curLod),
                };
                //int layerDataIdx = chuncklayer.layerSize == mapChuckCfg.chunckSize ? 1 : (mapChuckCfg.chunckSize / chuncklayer.layerSize);
                //chuncklayer.SetLayerDataSize(layerDataIdx * layerDataIdx);
                chuncklayer.SetLayerDataSize(1);
                // 4 添加层级对象 
                for (int ii = 0; ii < layer.transform.childCount; ii++)
                {
                    Transform element = layer.transform.GetChild(ii);
                    int level = 1;// 性能分级
                    if (MapChunckLevelMap != null && MapChunckLevelMap.ContainsKey(element.gameObject))
                    {
                        int _level = MapChunckLevelMap[element.gameObject];
                        if (_level > 0) level = _level;
                    }
                    if (chuncklayer.layerID == WorldEntry.MOUNTAINRANGE_LAYER_ID || chuncklayer.layerID == WorldEntry.PLANE_LAYER_ID)
                    {
                        level = 0;// 地表 阻挡 默认不会被性能删除
                    }
                    AddTileElementsData(element, chuncklayer, mapChuckCfg.chunckSize, level); 
                }
                mapChuckCfg.AddMapLayer(chuncklayer);
            }
            // 5 添加出生点层级 
            if(curLod == 1) // 只存储lod1的出生点数据
            {
                // 先加载对应的出生点数据 
                string pointDataPath = "Assets/Editor/EditorCfg/MapData/" + name + "_pointdata.txt";
                TextAsset content = AssetDatabase.LoadAssetAtPath<TextAsset>(pointDataPath);
                if (content != null && content.text != null && content.text.Length > 0)
                {
                    MapChunckLayer chuncklayer = new MapChunckLayer
                    {
                        layerID = WorldEntry.MAP_POINT_ID,
                        name = WorldEntry.MAP_POINT_NAME,
                        layerSize = WorldEntry.GetLayerSizeByLod(WorldEntry.MAP_POINT_ID, curLod),
                    };
                    chuncklayer.SetLayerDataSize(1);
                    // 解析出生点数据
                    var csvText = content.text.Trim();
                    var lines = csvText.Split(new char[1] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
                    //
                    for (int i = 2; i < lines.Length; i++)
                    {
                        var l = lines[i];
                        var data = l.Split(',');

                        if (data.Length == 4)
                        {
                            float.TryParse(data[1], out float x);
                            float.TryParse(data[2], out float z);
                            int.TryParse(data[3], out int type);
                            int resId0 = 0;
                            if (type == (int)WorldEntry.MapPointType.E_Alliance)
                            {
                                resId0 = 2;
                            }
                            else if (type == (int)WorldEntry.MapPointType.E_CityAndRes || type == (int)WorldEntry.MapPointType.E_City)
                            {
                                resId0 = 1;
                            }
                            else if (type == (int)WorldEntry.MapPointType.E_RallyPoint)
                            {
                                resId0 = 1; 
                            }
                            else if (type == (int)WorldEntry.MapPointType.E_Res)
                            {
                                resId0 = 1;
                            }
                            else
                            { 
                                // 其他类型暂时不导出
                            }
                            if(resId0 > 0)
                            {
                                Vector3 euler = Vector3.zero;
                                var tileElement = new TileElement(new Vector3(x,0,z), euler, Vector3.one, resId0, type, 0);
                                chuncklayer.AddChunckElement(tileElement, 0);
                            }
                        }
                    }
                    mapChuckCfg.AddMapLayer(chuncklayer);
                }
                else
                {
                    //EditorUtility.DisplayDialog("错误", "导出对应地图块的时候没有对应的地图块出生点数据 ：" + pointDataPath, "ok");
                    //return false;
                }
            }
            string chunckDataPath = savePath + "/" + name + "_chuckData.asset";
            AssetDatabase.CreateAsset(mapChuckCfg, chunckDataPath);
            int chunckId = GetMapChunckPrefabId(chunckDataPath);

            // 导出lod3地图数据
            string mapChuckName = CreateMapEditorWindow.StrReplace(mapChuck.gameObject.name, "lod1", "lod3");
            ExportMapChuckLod3Cfg(mapChuckName, chunckId);
            // 导出最新地图映射
            if (bExportMapPrefabMap)
            { 
                ExportMapPrefabMap();
            }
            return true;
        }

        public void ExportMapChuckLod3Cfg(string mapChuckName, int chunckId)
        {
            MapChunckData mapChuckCfg = ScriptableObject.CreateInstance<MapChunckData>();
            mapChuckCfg.chunckSize = WorldEntry.m_iTileSize;
            int curLod = GetMapChunckLod(mapChuckName);
            MapChunckLayer chuncklayer = new MapChunckLayer
            {
                layerID = WorldEntry.PLANE_LAYER_ID,
                name = WorldEntry.PLANE_LAYER_NAME,
                layerSize = WorldEntry.GetLayerSizeByLod(WorldEntry.PLANE_LAYER_ID, curLod),
            };

            int layerDataIdx = chuncklayer.layerSize == mapChuckCfg.chunckSize ? 1 : (mapChuckCfg.chunckSize / chuncklayer.layerSize);
            chuncklayer.SetLayerDataSize(layerDataIdx * layerDataIdx);
            chunckInfoDta chucckDta = GetChunckInfoById(chunckId);
            chucckDta.lod = 3;
            chucckDta.radio = 0;
            int prefabLod = chucckDta.lod;
            if (chucckDta.roadType == 117 || chucckDta.roadType == 119)
            {
                prefabLod = 1;// 海岛地图块太多了 不新增lod3
            }
            string objpath = string.Format("Assets/ResourcesAssets/World/prefabs/sandtable/tiles/lod{4}/sandtable_{0}_{1}_{2}_lod{3}.prefab",
               chucckDta.roadType, chucckDta.chunckType, chucckDta.radio, prefabLod, prefabLod);
            AddTileElementsData(objpath, chuncklayer, WorldEntry.m_iTileSize, chucckDta.radio);

            mapChuckCfg.AddMapLayer(chuncklayer);
            string chunckDataPath = savePath + "/" + mapChuckName + "_chuckData.asset";
            int chunckId_3 = GetMapChunckPrefabId(chunckDataPath);
            AssetDatabase.CreateAsset(mapChuckCfg, chunckDataPath);
        }

        // 导出所有地图块数据 
        string mapChuckCfgPath = "Assets/Arts/World/sandtable/prefabs/mapChunckEditor/";
        public bool ExportAllMapChuckCfg()
        {
            bool res = true;
            string[] mapChunckPaths = AssetDatabase.FindAssets("t:prefab", new[] { mapChuckCfgPath });
            for (int idx = 0; idx < mapChunckPaths.Length; idx++)
            {
                string guid = mapChunckPaths[idx];
                string assetPath = AssetDatabase.GUIDToAssetPath(guid);
                GameObject obj = AssetDatabase.LoadAssetAtPath<GameObject>(assetPath);
                ExportMapChuckCfg(obj, null,false);
            }
            ExportMapPrefabMap();
            return res;
        }

        // 导入地图块映射 id -> 配置名
        public static void ExportMapPrefabMap()
        {
            // 按照路径导出预制体对应文件
            if (!File.Exists(MapPrefabMapPath))
            {
                File.Delete(MapPrefabMapPath);
            }
            MapPrefabMap mapPrefabMap = ScriptableObject.CreateInstance<MapPrefabMap>();
            // 写入道路信息
            foreach (string path in MapPrefabMap.Keys)
            {
                PrefabData prefab = new PrefabData(MapPrefabMap[path], path, 0);
                if (prefab.resID > 100)
                {
                    // resID > 100的资源路径需要做检查 如果不存在删除
             
                    if (!File.Exists(prefab.resPath))// 检查一下data存在
                    {
                        Debug.LogError("[ExportMapPrefabMap] 文件不存在 => " + path);
                        continue;
                    }
                }
                mapPrefabMap.AddMapPrefabMap(prefab);
            }
            AssetDatabase.CreateAsset(mapPrefabMap, MapPrefabMapPath);
            AssetDatabase.Refresh();
        }

        public static void CheckMapPrefabMap()
        {
            InportMapPrefabMap();
            ExportMapPrefabMap();
        }

        // 获得地图预制体id
        public static int GetMapPrefabId(string prefabPath)
        {
            if (!File.Exists(prefabPath))
            {
                Debug.LogError("[地图预制体映射] ============================= 未查询到对应预制体：" + prefabPath);
            }
            int id = -1;
            InportMapPrefabMap();
            if (MapPrefabMap.ContainsKey(prefabPath))
            {
                id = MapPrefabMap[prefabPath];
            }
            else
            {
                id = MapPrefabMaxId++;
                MapPrefabMap[prefabPath] = id;
            }
            return id;
        }


        // 获得地图块预制体id
        public static int GetMapChunckPrefabId(string prefabPath)
        {
            int id = -1;
            // 拆分prefabPath
            //"Assets/Arts/World/sandtable/prefabs/mapChunckEditor/sandtable_100_2_0_lod1.prefab";
            chunckInfoDta data = new chunckInfoDta();
            var paths = prefabPath.Split("/");
            string path = paths[paths.Length - 1];
            string[] strArr = path.Split('_');
            int.TryParse(strArr[1], out data.roadType);
            int.TryParse(strArr[2], out data.chunckType);
            int.TryParse(strArr[3], out data.radio);
            data.lod = GetMapChunckLod(path);
            int chunckId = GetChunckIdByInfo(data);
            InportMapPrefabMap();
            if (MapPrefabMap.ContainsKey(prefabPath))
            {
                id = MapPrefabMap[prefabPath];
            }
            else
            {
                MapPrefabMap[prefabPath] = chunckId;
                id = chunckId;
            }
            return id;
        }

        // 获得地图预制体id
        public static string GetMapPrefabPath(int id)
        {
            string prefabPath = "";
            InportMapPrefabMap();
            if (MapPrefabMapIdToPath.ContainsKey(id))
            {
                prefabPath = MapPrefabMapIdToPath[id];
            }
           
            return prefabPath;
        }

        // 获得地图块对应层级
        public static int GetMapChunckLod(string chunckName)
        {
            int lod =0;// 默认0
            string[] strArr = chunckName.Split('_');
            for (int i = 0;i < strArr.Length;i++)
            {
                string str = strArr[i];
                if (str.Contains("lod"))
                {
                    int.TryParse(str[str.Length - 1].ToString(), out lod);
                    break;
                }
            }
            return lod;
        }

        private static void AddTileElementsData(Transform transform, MapChunckLayer layerData, int tileSize, int level = 0)
        {
            int index1 = transform.gameObject.name.IndexOf('<');
            int index2 = transform.gameObject.name.LastIndexOf('>');
            string objpath = transform.gameObject.name.Substring(index1 + 1, index2 - index1 - 1);
            string assetPath = "";
            if (objpath != null)
            {
                assetPath = objpath;
            }
            if (assetPath.Equals(""))
            {
                assetPath = "Assets/ResourcesAssets/World/prefabs/MissingPrefab.prefab";
            }
            if (assetPath.Contains("Arts"))
            {
                Debug.LogError("[地图块导出] ============================= 存在art路径下预制体：" + assetPath);
                EditorUtility.DisplayDialog("警告", "存在art路径下预制体！！！！！！！！！！！！！！", "ok");
                return;
            }
            int resID = GetMapPrefabId(assetPath);
            Vector3 euler = transform.eulerAngles;
            //if (resID == 130)
            //{
            //    level = 2;// 如果是lod1的 云 特殊处理 
            //}
            var tileElement = new TileElement(transform.position, euler, transform.localScale, resID, 0, level);
            int elementDataIdx = 0;
            if (tileSize != layerData.layerSize)// 说明当前层级数据 存在粒度 需要对tileElement计算数据所在idx 已舍弃
            {
                //int sizeNum = tileSize / layerData.layerSize;
                //int idx_x = (int)((transform.position.x + tileSize * 0.5f) / layerData.layerSize);
                //int idx_z = (int)((transform.position.z + tileSize * 0.5f) / layerData.layerSize);
                //elementDataIdx = idx_x + idx_z * sizeNum;
            }
            layerData.AddChunckElement(tileElement, elementDataIdx);
        }

        private static void AddTileElementsData(string objpath, MapChunckLayer layerData, int tileSize,int radio)
        {
            string assetPath = "";
            if (objpath != null)
            {
                assetPath = objpath;
            }
            if (assetPath.Equals(""))
            {
                assetPath = "Assets/ResourcesAssets/World/prefabs/MissingPrefab.prefab";
            }
            int resID = GetMapPrefabId(assetPath);
            Vector3 euler = new Vector3(0, 90 * radio, 0);
            Vector3 position = new Vector3(0, 0, 0);
            var tileElement = new TileElement(position, euler, Vector3.one, resID, 0, 0);
            layerData.AddChunckElement(tileElement, 0);
        }

        private static void AddTileAllianceRoadData(Transform layer, MapChunckData chunckData)
        {
            for (int i = 0; i < layer.childCount; i++)
            {
                Transform transform = layer.GetChild(i);
                int index1 = transform.gameObject.name.IndexOf('<');
                int index2 = transform.gameObject.name.LastIndexOf('>');
                string objpath = transform.gameObject.name.Substring(index1 + 1, index2 - index1 - 1);
                string assetPath = "";
                if (objpath != null)
                {
                    assetPath = objpath;
                }
                if (assetPath.Equals(""))
                {
                    assetPath = "Assets/ResourcesAssets/World/prefabs/MissingPrefab.prefab";
                }
                int resID = GetMapPrefabId(assetPath);
                int localIdx = transform.GetSiblingIndex();
                var road = new TileAlliancePointRoad(transform.position, resID, localIdx);
                chunckData.AddChunckePointRoad(road);
            }
        }

        private static void AddTileAllianceCrossData(Transform layer, MapChunckData chunckData)
        {
            for (int i = 0; i < layer.childCount; i++)
            {
                Transform transform = layer.GetChild(i);
                int index1 = transform.gameObject.name.IndexOf('<');
                int index2 = transform.gameObject.name.LastIndexOf('>');
                string objpath = transform.gameObject.name.Substring(index1 + 1, index2 - index1 - 1);
                string assetPath = "";
                if (objpath != null)
                {
                    assetPath = objpath;
                }
                if (assetPath.Equals(""))
                {
                    assetPath = "Assets/ResourcesAssets/World/prefabs/MissingPrefab.prefab";
                }
                int resID = GetMapPrefabId(assetPath);
                int idx = transform.GetSiblingIndex();
                int lcoalIdx = (int)Mathf.Floor(idx / 4);
                int angleIdx = idx % 4;
                var cross = new TileAlliancePointCross(transform.position, resID, lcoalIdx, angleIdx);
                chunckData.AddChunckePointCross(cross);
            }
        }

        private static void AddTilePointAdornData(Transform layer, MapChunckData chunckData)
        {
            PointAdornRoot rootScript = layer.GetComponent<PointAdornRoot>();
            if (rootScript)
            {
                rootScript.FindAdorn();
                List<PointAdorn> adorns = rootScript.GetAdorns();
                if (adorns != null)
                {
                    Dictionary<int, TilePointAdornData> level_n = new Dictionary<int, TilePointAdornData>();
                    Dictionary<int, TilePointAdornData> level_2 = new Dictionary<int, TilePointAdornData>();
                    Dictionary<int, TilePointAdornData> level_1 = new Dictionary<int, TilePointAdornData>();
                    Dictionary<int, TilePointAdornData> level_null = new Dictionary<int, TilePointAdornData>();
                    Dictionary<int, TilePointAdornData> level_road = new Dictionary<int, TilePointAdornData>();
                    int uid0 = 1;
                    for (int i = 0; i < adorns.Count; i++)
                    {
                        PointAdorn adorn = adorns[i];
                        if (adorn.pointObjs == null || adorn.pointObjs.Count <= 0) continue;
                       
                        Transform transform = adorn.transform;
                        Debug.Log("[装饰物] 导出装饰物 =============================== " + i, transform.gameObject);
                        int index1 = transform.gameObject.name.IndexOf('<');
                        int index2 = transform.gameObject.name.LastIndexOf('>');
                        string objpath = transform.gameObject.name.Substring(index1 + 1, index2 - index1 - 1);
                        string assetPath = "";
                        if (objpath != null)
                        {
                            assetPath = objpath;
                        }
                        if (assetPath.Equals(""))
                        {
                            assetPath = "Assets/ResourcesAssets/World/prefabs/MissingPrefab.prefab";
                        }
                        if (assetPath.Equals("0类型连接出生点装饰物"))
                        {
                            assetPath = "Assets/ResourcesAssets/World/prefabs/MissingPrefab.prefab";
                        }
                        int resID = GetMapPrefabId(assetPath);
                        TilePointAdornData data = adorn.GetPointAdornData();
                        data.uid = uid0;
                        if (data != null)
                        {
                            data.resId = resID;
                            //[1,4] 代表方向 顺时针 [5,8] 代表边 顺时针 上右下左 10 代表三级装饰物 9 代表衔接道路 11 代表空置装饰物 -1无效值 0无 但是表示两出生点相连
                            if (data.type == 0)
                            {
                                level_2[data.uid] = data;
                            }
                            else if (data.type <= 4)
                            {
                                level_1[data.uid] = data;
                            }
                            else if (data.type <= 8)
                            {
                                level_2[data.uid] = data;
                            }
                            else if (data.type == 9)
                            {
                                level_road[data.uid] = data;
                            }
                            else if (data.type == 10)
                            {
                                level_n[data.uid] = data;
                            }
                            else if (data.type == 11)
                            {
                                level_null[data.uid] = data;
                            }
                            uid0++;
                        }
                    
                    }

                    // 设置上下级数据

                    // 多级设置low
                    foreach (int uid in level_n.Keys)
                    {
                        TilePointAdornData data = level_n[uid];
                        List<int> pointIdxs = data.pointIdxs;
                        foreach (int uid2 in level_2.Keys)
                        {
                            TilePointAdornData data2 = level_2[uid2];
                            List<int> point2Idxs = data2.pointIdxs;
                            if (pointIdxs.Contains(point2Idxs[0]) || pointIdxs.Contains(point2Idxs[1]))
                            {
                                data.AddLow(data2.uid);
                            }
                        }
                    }

                    // 二级设置hight low
                    foreach (int uid2 in level_2.Keys)
                    {
                        TilePointAdornData data2 = level_2[uid2];
                        List<int> point2Idxs = data2.pointIdxs;
                        foreach (int uid in level_n.Keys)
                        {
                            TilePointAdornData data = level_n[uid];
                            List<int> pointIdxs = data.pointIdxs;
                            if (pointIdxs.Contains(point2Idxs[0]) || pointIdxs.Contains(point2Idxs[1]))
                            {
                                data2.AddHight(data.uid);
                            }
                        }

                        foreach (int uid1 in level_1.Keys)
                        {
                            TilePointAdornData data1 = level_1[uid1];
                            List<int> point1Idxs = data1.pointIdxs;

                            if (point2Idxs[0] == point1Idxs[0])
                            {
                                bool bAddLow = false;
                                if (data2.type == 5)
                                {
                                    bAddLow = data1.type == 4 || data1.type == 1;
                                }
                                else if (data2.type == 6)
                                {
                                    bAddLow = data1.type == 1 || data1.type == 2;
                                }
                                else if (data2.type == 7)
                                {
                                    bAddLow = data1.type == 2 || data1.type == 3;
                                }

                                else if (data2.type == 8)
                                {
                                    bAddLow = data1.type == 3 || data1.type == 4;
                                }

                                if (bAddLow)
                                {
                                    data2.AddLow(data1.uid);
                                }
                            }

                            if (point2Idxs[1] == point1Idxs[0])
                            {
                                bool bAddLow = false;
                                if (data2.type == 5)
                                {
                                    bAddLow = data1.type == 3 || data1.type == 2;
                                }
                                else if (data2.type == 6)
                                {
                                    bAddLow = data1.type == 3 || data1.type == 4;
                                }
                                else if (data2.type == 7)
                                {
                                    bAddLow = data1.type == 4 || data1.type == 1;
                                }

                                else if (data2.type == 8)
                                {
                                    bAddLow = data1.type == 1 || data1.type == 2;
                                }

                                if (bAddLow)
                                {
                                    data2.AddLow(data1.uid);
                                }
                            }
                        }
                    }

                    // 一级添加hight
                    foreach (int uid1 in level_1.Keys)
                    {
                        TilePointAdornData data1 = level_1[uid1];
                        List<int> point1Idxs = data1.pointIdxs;
                        foreach (int uid2 in level_2.Keys)
                        {
                            TilePointAdornData data2 = level_2[uid2];
                            List<int> point2Idxs = data2.pointIdxs;

                            if (point2Idxs[0] == point1Idxs[0])
                            {
                                bool bAdd = false;
                                if (data2.type == 5)
                                {
                                    bAdd = data1.type == 4 || data1.type == 1;
                                }
                                else if (data2.type == 6)
                                {
                                    bAdd = data1.type == 1 || data1.type == 2;
                                }
                                else if (data2.type == 7)
                                {
                                    bAdd = data1.type == 3 || data1.type == 3;
                                }

                                else if (data2.type == 8)
                                {
                                    bAdd = data1.type == 3 || data1.type == 4;
                                }

                                if (bAdd)
                                {
                                    data1.AddHight(data2.uid);
                                }
                            }


                            if (point2Idxs[1] == point1Idxs[0])
                            {
                                bool bAdd = false;
                                if (data2.type == 5)
                                {
                                    bAdd = data1.type == 2 || data1.type == 3;
                                }
                                else if (data2.type == 6)
                                {
                                    bAdd = data1.type == 3 || data1.type == 4;
                                }
                                else if (data2.type == 7)
                                {
                                    bAdd = data1.type == 4 || data1.type == 1;
                                }

                                else if (data2.type == 8)
                                {
                                    bAdd = data1.type == 1 || data1.type == 2;
                                }

                                if (bAdd)
                                {
                                    data1.AddHight(data2.uid);
                                }
                            }

                        }
                    }

                    foreach (var data in level_n.Values)
                    {
                        chunckData.AddChunckePointAdorn(data);
                    }
                    foreach (var data in level_2.Values)
                    {
                        chunckData.AddChunckePointAdorn(data);
                    }
                    foreach (var data in level_1.Values)
                    {
                        chunckData.AddChunckePointAdorn(data);
                    }
                    foreach (var data in level_null.Values)
                    {
                        chunckData.AddChunckePointAdorn(data);
                    }
                    foreach (var data in level_road.Values)
                    {
                        chunckData.AddChunckePointAdorn(data);
                    }
                }
            }
            else
            {
                Debug.LogError("[沙盘编辑器] -地图块配置导出 | 存在未绑定的装饰物层级：" + layer.parent.gameObject.name);
            }
        }

        // ============================== 其他 ==============================

        public class chunckInfoDta {
            public int roadType;
            public int chunckType;
            public int radio;
            public int lod;

            public chunckInfoDta()
            {
            }
            public chunckInfoDta(chunckInfoDta data)
            {
                this.roadType = data.roadType;
                this.chunckType = data.chunckType;
                this.radio = data.radio;
                this.lod = data.lod;
            }
        }

        //sandtable_道路类型_地表分布_旋转_lod层级
        //道路类型：1~n
        //地表分布：1~n
        //地表分布：0 -0° 1 -90° 2 -180° 3 -270°
        //lod层级：lod1 -对应沙盘lod1 ~lod2地表 lod3 -对应沙盘lod3 ~lod4地表
        //sandtable_2_3_0_lod1 对应配置id 2 * 1000000 + 3 * 10000 +  0*10 + 1*1
        // 解析地图块id 
        public static chunckInfoDta GetChunckInfoById(int chunckId)
        {
            chunckInfoDta data = new chunckInfoDta();
            data.roadType = chunckId / 1000000;
            data.chunckType = (chunckId % 1000000) / 10000;
            data.radio = (chunckId % 10000) / 10;
            data.lod = chunckId % 10;
            return data;
        }

        public static int GetChunckIdByInfo(chunckInfoDta data)
        {
            int id = 0;
            id = data.roadType * 1000000 + data.chunckType * 10000 + data.radio * 10 + data.lod * 1;
            return id;
        }


        public static bool judgeMapPointHideByRoad(Vector3 pos, int type = -1)
        {
            bool hide = false;
            // 如果传入类型 是点位判断 
            if (type >= 0)
            {
                if (type == (int)WorldEntry.MapPointType.E_Alliance || 
                    type == (int)WorldEntry.MapPointType.E_Wonder || 
                    type == (int)WorldEntry.MapPointType.E_Checkpoint ||
                    type == (int)WorldEntry.MapPointType.E_RallyPoint ||
                    type == (int)WorldEntry.MapPointType.E_StationPoint)
                {
                    return hide;
                }
            }
            Collider[] colliders = Physics.OverlapSphere(pos, 2f);// 半径尽量大一点
            for (int i = 0; i < colliders.Length; i++)
            {
                Collider collider = colliders[i];
                if (collider && collider.gameObject)
                {
                    if (collider.gameObject.name.Contains("road"))
                    {
                        hide = true;
                        break;
                    }
                }
            }
            return hide;
        }
        public static Vector3 GetPosByAngle(Vector3 pos_0, int angle)
        {
            Vector3 pos = new Vector3(pos_0.x, pos_0.y, pos_0.z);
            if (angle == 1) // 90
            {
                pos.x = pos_0.z;
                pos.z = -pos_0.x;
            }
            else if (angle == 2)// 180
            {
                pos.x = -pos_0.x;
                pos.z = -pos_0.z;
            }
            else if (angle == 3)// 270
            {
                pos.x = -pos_0.z;
                pos.z = pos_0.x;
            }
            
            return pos;
        }

        public static bool _OpenWorldMapData(WorldMapData mapdata, Dictionary<int, Color> colors,bool bShowOverSeaChunck = false)
        {
            InportMapPrefabMap();

            if (mapdata == null)
                return false;
            //------------------------------------------------------------------------------------------------------------------------生成节点 初始化脚本
            var time = DateTime.Now;
            GameObject MapRoot = new GameObject(mapdata.name.Replace("_mapdata", ""));
            var mapEditorHelperObj = MapRoot.AddComponent<MapEditorHelper>();
            mapEditorHelperObj.mapName = MapRoot.name;

            mapEditorHelperObj.savePath = savePath;
            mapEditorHelperObj.tilesPath = tilesPath;
            //------------------------------------------------------------------------------------------------------------------------生成层级
            MapLODData lodData = mapdata.mapLODDatas[0];
            mapEditorHelperObj.Lod = (int)lodData.lodDistance;
            mapEditorHelperObj.Size = lodData.tileSize;
            mapEditorHelperObj.TILE_HEIGHT = lodData.tileSize;
            mapEditorHelperObj.TILE_WIDTH = lodData.tileSize;
            mapEditorHelperObj.wSize = mapdata.mapWidth / lodData.tileSize;
            mapEditorHelperObj.hSize = mapdata.mapHeight / lodData.tileSize;
            //
            int lineNum = mapdata.mapWidth / lodData.tileSize;
            string path_editor = "Assets/Arts/World/sandtable/prefabs/editor/sandtable_terrain01_editor_lod1.prefab";
            GameObject chunck = (GameObject)AssetDatabase.LoadAssetAtPath<GameObject>(path_editor);
            for (int i = 0; i < lodData.mapChunckIds.Count; i++)
            {
                int x = i % lineNum;
                int y = i / lineNum;
                // 依次生成地块到MapRoot
                int chuckId = lodData.mapChunckIds[i];
                chunckInfoDta chucckDta = GetChunckInfoById(chuckId);

                float radio = chucckDta.radio;
                if (radio > 0) radio = 0;

                string chunckName = string.Format("Assets/ResourcesAssets/World/prefabs/sandtable/tiles/lod{4}/sandtable_{0}_{1}_{2}_lod{3}.prefab", 
                    chucckDta.roadType, chucckDta.chunckType, radio, chucckDta.lod, chucckDta.lod);
                GameObject chunck_obj = null;
                // 存在固定4车道的地图块
                chunck_obj = (GameObject)AssetDatabase.LoadAssetAtPath<GameObject>(chunckName);
                if (chunck_obj == null)
                {
                    Debug.Log("_OpenWorldMapData ============================= create chunck err " + " chunckId : " + chuckId + "name : " + chunckName);
                    continue;
                }
                chunck_obj = GameObject.Instantiate(chunck_obj);

                chunck_obj.name = "TILE<" + chunckName + ">";
             
                float halfSize = lodData.tileSize * 0.5f;
                chunck_obj.transform.position = new Vector3(halfSize + lodData.tileSize * x, 0, halfSize + lodData.tileSize * y);
                chunck_obj.transform.rotation = Quaternion.Euler(new Vector3(0,90 * chucckDta.radio, 0));
                chunck_obj.transform.parent = MapRoot.transform;
            }
            if (bShowOverSeaChunck)
            {
                GameObject MapRootTemp = new GameObject(mapdata.name.Replace("_mapdata", "") +"_无用海外地图块"); 
                for (int i = 0; i < lodData.mapOverSeaChuncks.Count; i++)
                {
                    OverSeaChunck chunckInfo = lodData.mapOverSeaChuncks[i];
                    int x = chunckInfo.offset_x;
                    int y = chunckInfo.offset_y;
                    if (x < 0 || y < 0)
                    {
                        int chuckId = chunckInfo.chunckId;
                        chunckInfoDta chucckDta = GetChunckInfoById(chuckId);

                        float radio = chucckDta.radio;
                        if (radio > 0) radio = 0;

                        string chunckName = string.Format("Assets/ResourcesAssets/World/prefabs/sandtable/tiles/lod{4}/sandtable_{0}_{1}_{2}_lod{3}.prefab",
                            chucckDta.roadType, chucckDta.chunckType, radio, chucckDta.lod, chucckDta.lod);
                        GameObject chunck_obj = null;
                        // 存在固定4车道的地图块
                        chunck_obj = (GameObject)AssetDatabase.LoadAssetAtPath<GameObject>(chunckName);
                        if (chunck_obj == null)
                        {
                            Debug.Log("_OpenWorldMapData ============================= create chunck err " + " chunckId : " + chuckId + "name : " + chunckName);
                            continue;
                        }
                        chunck_obj = GameObject.Instantiate(chunck_obj);

                        chunck_obj.name = "TILE<" + chunckName + ">";

                        float halfSize = lodData.tileSize * 0.5f;
                        chunck_obj.transform.position = new Vector3(halfSize + lodData.tileSize * x, 0, halfSize + lodData.tileSize * y);
                        chunck_obj.transform.rotation = Quaternion.Euler(new Vector3(0, 90 * chucckDta.radio, 0));
                        chunck_obj.transform.parent = MapRootTemp.transform;
                    }
                }
            }
            return true;
        }

        public static GameObject _CreateWonderEditorCross(WorldMapData mapdata)
        {
            InportMapPrefabMap();
            LoadMapFogData();
            if (mapdata == null)
                return null;
            //------------------------------------------------------------------------------------------------------------------------生成节点 初始化脚本
            GameObject crossRoot = new GameObject("奇观衔接点-根节点");
            //------------------------------------------------------------------------------------------------------------------------生成层级
            MapLODData lodData = mapdata.mapLODDatas[0];
            int lineNum = mapdata.mapWidth / lodData.tileSize;
            for (int i = 0; i < lodData.mapChunckIds.Count; i++)
            {
                int x = i % lineNum;
                int y = i / lineNum;
                // 依次生成地块到MapRoot
                int chuckId = lodData.mapChunckIds[i];
                chunckInfoDta chucckDta = GetChunckInfoById(chuckId);

                float radio = chucckDta.radio;
                if (radio > 0) radio = 0;

                if (!(chucckDta.roadType == 100 || chucckDta.roadType == 101)) continue;
                string chunckName = string.Format("Assets/Arts/World/sandtable/prefabs/editor/WonderCross/sandtable_{0}_{1}_{2}_lod{3}_wonder_cross.prefab",
                    chucckDta.roadType, chucckDta.chunckType, radio, chucckDta.lod);
                GameObject chunck_obj = null;
                // 存在固定4车道的地图块
                chunck_obj = (GameObject)AssetDatabase.LoadAssetAtPath<GameObject>(chunckName);
                if (chunck_obj == null)
                {
                    Debug.Log("_CreateWonderEditorCross ============================= create cross err " + " chunckId : " + chuckId + "name : " + chunckName);
                    continue;
                }
                chunck_obj = GameObject.Instantiate(chunck_obj);
         

                float halfSize = lodData.tileSize * 0.5f;
                chunck_obj.transform.position = new Vector3(halfSize + lodData.tileSize * x, 0, halfSize + lodData.tileSize * y);
                chunck_obj.transform.rotation = Quaternion.Euler(new Vector3(0, 90 * chucckDta.radio, 0));
                chunck_obj.transform.parent = crossRoot.transform;

                //
                int fogIdx = GetFogIdx(chunck_obj.transform.position);
                int wonderId = GetFogIdByIndex(fogIdx);
                chunck_obj.name = wonderId.ToString();
            }
            return crossRoot;
        }

        public static GameObject _CreateWonderEditorCenter(WorldMapData mapdata)
        {
            InportMapPrefabMap();
            LoadMapFogData();
            if (mapdata == null)
                return null;
            //------------------------------------------------------------------------------------------------------------------------生成节点 初始化脚本
            GameObject centerRoot = new GameObject("奇观中心点-根节点");
            //------------------------------------------------------------------------------------------------------------------------生成层级
            MapLODData lodData = mapdata.mapLODDatas[0];
            int lineNum = mapdata.mapWidth / lodData.tileSize;
            for (int i = 0; i < lodData.mapChunckIds.Count; i++)
            {
                int x = i % lineNum;
                int y = i / lineNum;
                // 依次生成地块到MapRoot
                int chuckId = lodData.mapChunckIds[i];
                chunckInfoDta chucckDta = GetChunckInfoById(chuckId);

                float radio = chucckDta.radio;
                if (radio > 0) radio = 0;

                if (!(chucckDta.roadType == 100 || chucckDta.roadType == 101)) continue;
                string chunckName = string.Format("Assets/Arts/World/sandtable/prefabs/editor/WonderCross/sandtable_{0}_{1}_{2}_lod{3}_wonder_center.prefab",
                    chucckDta.roadType, chucckDta.chunckType, radio, chucckDta.lod);
                GameObject chunck_obj = null;
                // 存在固定4车道的地图块
                chunck_obj = (GameObject)AssetDatabase.LoadAssetAtPath<GameObject>(chunckName);
                if (chunck_obj == null)
                {
                    Debug.Log("_CreateWonderEditorCross ============================= create cross err " + " chunckId : " + chuckId + "name : " + chunckName);
                    continue;
                }
                chunck_obj = GameObject.Instantiate(chunck_obj);
         

                float halfSize = lodData.tileSize * 0.5f;
                chunck_obj.transform.position = new Vector3(halfSize + lodData.tileSize * x, 0, halfSize + lodData.tileSize * y);
                //chunck_obj.transform.rotation = Quaternion.Euler(new Vector3(0, 90 * chucckDta.radio, 0));
                chunck_obj.transform.parent = centerRoot.transform;

                //
                int fogIdx = GetFogIdx(chunck_obj.transform.position);
                int wonderId = GetFogIdByIndex(fogIdx);
                chunck_obj.name = wonderId.ToString();
            }
            return centerRoot;
        }

        public static void CropWorldMapData(WorldMapData mapdata, Vector4 cropV4)
        {
            int X_L = (int)cropV4.x;
            int X_R = (int)cropV4.y;
            int Y_B = (int)cropV4.z;
            int Y_T = (int)cropV4.w;
            var mapData = ScriptableObject.CreateInstance<WorldMapData>();
            mapData.mapWidth = mapdata.mapWidth - (X_L + X_R) * WorldEntry.m_iTileSize;
            mapData.mapHeight = mapdata.mapWidth - (Y_B + Y_T) * WorldEntry.m_iTileSize;
            mapData.name = mapdata.name;
            int oldLineNum = mapdata.mapWidth / WorldEntry.m_iTileSize;
            // 拷贝 lod1的数据
            MapLODData lodData = new MapLODData()
            {
                lodDistance = 1,
                tileSize = WorldEntry.m_iTileSize,
            };
            MapLODData lodData1 = mapdata.mapLODDatas[0];
            for (int i = 0; i < lodData1.mapChunckIds.Count; i++)
            {
                int x = i % oldLineNum;
                int y = i / oldLineNum;
                // 判断改坐标在裁切范围内
                bool dataX = (x + 1) > X_L && x < (oldLineNum - X_R);
                bool dataY = (y + 1) > Y_B && y < (oldLineNum - Y_T);
                if (dataX && dataY)
                {
                    lodData.AddMapChunckId(lodData1.mapChunckIds[i]);
                }

            }
            mapData.AddLODData(lodData);
            string dataPath = "Assets/ResourcesAssets/World/mapdata/" + mapData.name + "_new.asset";
            //if (!File.Exists(dataPath))
            //{
            //    File.Delete(dataPath);
            //}
            AssetDatabase.CreateAsset(mapData, dataPath);
            //AssetDatabase.Refresh();
        }

        static Dictionary<int, GameObject> chunckObstruct;
        // 生成地图块阻挡 -关卡阻挡 -联盟点阻挡
        public static void CreateChunckObstruct(int chunckId, int idx, Transform root,Transform _editorRoot, OverSeaChunck info)
        {
            InportMapPrefabMap();

            if (chunckObstruct == null) chunckObstruct = new Dictionary<int, GameObject>();
            if (!chunckObstruct.ContainsKey(chunckId))
            {
                chunckInfoDta data = GetChunckInfoById(chunckId);
                chunckInfoDta data_0 = new chunckInfoDta(data);
                data_0.radio = 0;
                int chunckId_0 = GetChunckIdByInfo(data_0);
                string path_editor = MapPrefabMap.FirstOrDefault(q => q.Value == chunckId_0).Key;

                var asset = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(path_editor);
                if (asset)
                {
                    MapChunckData chunckData = asset as MapChunckData;
                    GameObject chunckObj = new GameObject();
                    chunckObj.transform.SetParent(root);
                    chunckObj.name = "地图块阻挡_" + chunckId;
                    chunckObj.transform.localRotation = Quaternion.Euler(new Vector3(0, 90 * data.radio, 0));
                    // 创建该地图块所有的碰撞点
                    for (int i = 0; i < chunckData.mapLayers.Count; i++)
                    {
                        var layer = chunckData.mapLayers[i];
                        if (layer.layerID == WorldEntry.PLANE_LAYER_ID)
                        {
                            // 加载碰撞
                            for (int ii = 0; ii < layer.elementDatas.Count; ii++)
                            {
                                var objDatas = layer.elementDatas[ii];
                                for (int iii = 0; iii < objDatas.elementDatas.Count; iii++)
                                {
                                    var objData = objDatas.elementDatas[iii];
                                    string path = MapPrefabMap.FirstOrDefault(q => q.Value == objData.resID).Key;
                                    var strArr = path.Split('/');
                                    string name = strArr[strArr.Length - 1].Split('.')[0];
                                    Transform tf = _editorRoot.Find(name);
                                    if (tf)
                                    {
                                        GameObject obj = tf.gameObject;
                                        obj = GameObject.Instantiate(obj, chunckObj.transform);
                                        obj.transform.localPosition = objData.position;
                                        obj.transform.localRotation = Quaternion.Euler(Vector3.zero);
                                        obj.name = "地图块阻挡_关卡";
                                        obj.SetActive(true);
                                    }
                                }
                            }
                        }
                        if (layer.layerID == WorldEntry.MAP_POINT_ID)
                        {
                            // 加载中立建筑碰撞
                            for (int ii = 0; ii < layer.elementDatas.Count; ii++)
                            {
                                var objDatas = layer.elementDatas[ii];
                                for (int iii = 0; iii < objDatas.elementDatas.Count; iii++)
                                {
                                    var point = objDatas.elementDatas[iii];
                                    if (point.pointType == (int)WorldEntry.MapPointType.E_Alliance)
                                    {
                                        GameObject obj = GameObject.CreatePrimitive(PrimitiveType.Sphere);
                                        obj.transform.SetParent(chunckObj.transform);
                                        obj.transform.localPosition = point.position;
                                        obj.transform.localScale = Vector3.one * 0.6f;
                                        obj.name = "地图块阻挡_据点";
                                
                                        var flag = StaticEditorFlags.NavigationStatic;
                                        GameObjectUtility.SetStaticEditorFlags(obj, flag);
                                        GameObjectUtility.SetNavMeshArea(obj, 1);
                                    }
                                    else if (point.pointType == (int)WorldEntry.MapPointType.E_Checkpoint)
                                    { 
                                        // 关卡阻挡放在了编辑器对应块中了 10 和 11都是横向支线河流 但是11 固定有桥梁
                                    }
                                   
                                }
                            }
                        }
                    }
                    chunckObstruct[chunckId] = chunckObj;
                    chunckObj.gameObject.SetActive(false); // 隐藏缓存
                    CreateChunck(chunckId, idx, root,null, info);
                }
            }
            else
            {
                CreateChunck(chunckId, idx, root, null, info);
            }
        }

        public static MapChunckDeleateData checkMapItemShowByRoad(int chunckId, int idx, Transform root)
        {
            InportMapPrefabMap();
            MapChunckDeleateData deleteData = new MapChunckDeleateData();

            // chunckId 可能存在旋转
            chunckInfoDta data = GetChunckInfoById(chunckId);
            chunckInfoDta data_0 = new chunckInfoDta(data);
            data_0.radio = 0;
            int chunckId_0 = GetChunckIdByInfo(data_0);
            string path_editor = MapPrefabMap.FirstOrDefault(q => q.Value == chunckId_0).Key;

            var asset = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(path_editor);
            if (asset)
            {
                // 偏移坐标
                int lineNum = WorldEntry.m_mapSize / WorldEntry.m_iTileSize;
                float offset_x = idx % lineNum + 0.5f;
                float offset_y = idx / lineNum + 0.5f;

                MapChunckData chunckData = asset as MapChunckData;

                // 创建该地图块所有的碰撞点
                for (int i = 0; i < chunckData.mapLayers.Count; i++)
                {
                    var layer = chunckData.mapLayers[i];
                    if (layer.layerID == WorldEntry.TREE_LAYER_ID)
                    {
                        // 加载中立建筑碰撞
                        for (int ii = 0; ii < layer.elementDatas.Count; ii++)
                        {
                            deleteData.deleateIdx = new List<int>();

                            var objDatas = layer.elementDatas[ii];
                            for (int iii = 0; iii < objDatas.elementDatas.Count; iii++)
                            {
                                var element = objDatas.elementDatas[iii];
                                Vector3 localPos = GetPosByAngle(element.position, data.radio);
                                Vector3 worldPos = new Vector3(localPos.x + offset_x * WorldEntry.m_iTileSize, 0,localPos.z + offset_y * WorldEntry.m_iTileSize);
                                // 出生点需要检测和道路的碰撞
                                bool hide = GeneralMap.judgeMapPointHideByRoad(worldPos);
                                if (hide)
                                {
                                    // 向大地图数据中写入装饰物删除记录
                                    deleteData.deleateIdx.Add(iii);
                                    //
                                    GameObject obj = GameObject.CreatePrimitive(PrimitiveType.Sphere);
                                    obj.transform.SetParent(root.transform);
                                    obj.transform.localPosition = worldPos;
                                    obj.transform.localScale = Vector3.one * 1f;
                                    obj.name = "地图块装饰物_删除";
                                }
                            }
                        }
                    }
                }
              
            }
            return deleteData;
        }

        static Dictionary<int, GameObject> chunckAlliancePoints;
        public static void CreateChunckAlliancePoint(int chunckId, int idx, Transform root)
        {
            InportMapPrefabMap();
            if (chunckAlliancePoints == null) chunckAlliancePoints = new Dictionary<int, GameObject>();
            if (!chunckAlliancePoints.ContainsKey(chunckId))
            {
                // chunckId 可能存在旋转
                chunckInfoDta data = GetChunckInfoById(chunckId);
                chunckInfoDta data_0 = new chunckInfoDta(data);
                data_0.radio = 0;
                int chunckId_0 = GetChunckIdByInfo(data_0);
                string path_editor = MapPrefabMap.FirstOrDefault(q => q.Value == chunckId_0).Key;

                var asset = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(path_editor);
                if (asset)
                {
                    MapChunckData chunckData = asset as MapChunckData;
                    GameObject chunckObj = new GameObject();
                    chunckObj.transform.SetParent(root);
                    chunckObj.name = "地图块出生点_" + chunckId;
                    chunckObj.transform.localRotation = Quaternion.Euler(new Vector3(0, 90 * data.radio, 0));
                    // 创建该地图块所有的碰撞点
                    for (int i = 0; i < chunckData.mapLayers.Count; i++)
                    {
                        var layer = chunckData.mapLayers[i];
                        if (layer.layerID == WorldEntry.MAP_POINT_ID)
                        {
                            // 加载中立建筑碰撞
                            for (int ii = 0; ii < layer.elementDatas.Count; ii++)
                            {
                                var objDatas = layer.elementDatas[ii];
                                for (int iii = 0; iii < objDatas.elementDatas.Count; iii++)
                                {
                                    var point = objDatas.elementDatas[iii];
                                    if (point.pointType == (int)WorldEntry.MapPointType.E_Alliance || point.pointType == (int)WorldEntry.MapPointType.E_RallyPoint)
                                    {
                                        GameObject obj = GameObject.CreatePrimitive(PrimitiveType.Sphere);
                                        obj.transform.SetParent(chunckObj.transform);
                                        obj.transform.localPosition = point.position;
                                        obj.transform.localScale = Vector3.one * 1.6f;
                                        obj.name = "地图块出生点_据点";
                                    }
                                }
                            }
                        }
                    }
                    chunckAlliancePoints[chunckId] = chunckObj;
                    chunckObj.gameObject.SetActive(false); // 隐藏缓存
                    CreateChunck(chunckId, idx, root, chunckAlliancePoints);
                }
            }
            else
            {
                CreateChunck(chunckId, idx, root, chunckAlliancePoints);
            }
        }

        public static void CreateChunck(int chunckId, int idx, Transform root, Dictionary<int, GameObject> map = null, OverSeaChunck info = null)
        {
            GameObject newChunckObj = null;
            if (map != null){
                newChunckObj = map[chunckId];
            }
            else {
                newChunckObj = chunckObstruct[chunckId];
            }
            newChunckObj = GameObject.Instantiate(newChunckObj, root);
            newChunckObj.gameObject.SetActive(true);
            // 偏移坐标
            int lineNum = WorldEntry.m_mapSize / WorldEntry.m_iTileSize;
            float offset_x = idx % lineNum + 0.5f;
            float offset_y = idx / lineNum + 0.5f;
            if (info != null)
            {
                offset_x = info.offset_x + 0.5f;
                offset_y = info.offset_y + 0.5f;
            }
            newChunckObj.transform.position = new Vector3(offset_x * WorldEntry.m_iTileSize, 0, offset_y * WorldEntry.m_iTileSize);
        }

        public static GameObject CreateNullChunck(GameObject old)
        {
            GameObject obj = GameObject.Instantiate(old);
            for (int i = 0; i < obj.transform.childCount; i++)
            {
                Transform layer = obj.transform.GetChild(i);
                if (layer.name == WorldEntry.MOUNTAINRANGE_LAYER_NAME) continue;
                for (int ii = 0; ii < layer.transform.childCount; ii++)
                {
                    Transform lod = layer.transform.GetChild(ii);
                    for (int iii = 0; iii < lod.transform.childCount; iii++)
                    {
                        Transform Obj = lod.transform.GetChild(iii);
                        // 去除子节点
                        int childNum = Obj.transform.childCount;
                        for (int iiii = childNum - 1; childNum > 0 && iiii >= 0; iiii--)
                        {
                            Transform child = Obj.transform.GetChild(iiii);
                            GameObject.DestroyImmediate(child.gameObject);
                        }
                        // 去除组件 碰撞组件不能去除 需要导出碰撞数据
                        MeshFilter f = Obj.GetComponent<MeshFilter>();
                        if (f) GameObject.DestroyImmediate(f);
                        MeshRenderer r = Obj.GetComponent<MeshRenderer>();
                        if (r) GameObject.DestroyImmediate(r);
                    }
                }
            }
            return obj;
        }

        public static void OnDestroySelf()
        {
            if (chunckObstruct != null)
            {
                chunckObstruct.Clear();
            }
            if (chunckAlliancePoints != null)
            {
                chunckAlliancePoints.Clear();
            }
        }

        public static T Clone<T>(T RealObject)
        {
            if (RealObject == null) return default(T);
            using (Stream objectStream = new MemoryStream())
            {
                //利用 System.Runtime.Serialization序列化与反序列化完成引用对象的复制
                IFormatter formatter = new BinaryFormatter();
                formatter.Serialize(objectStream, RealObject);
                objectStream.Seek(0, SeekOrigin.Begin);
                return (T)formatter.Deserialize(objectStream);
            }
        }



        // ============================== 迷雾数据编辑器读取 ==============================

        private static WorldMapFogData m_mapFogData; // 原始地图迷雾数据
        private static Dictionary<int, List<Vector2Int>> m_mapFogTiles;// 迷雾占地数据 -用于设置采样图
        private static Dictionary<int, int> m_mapFogIdxToId; // 迷雾一维下标映射迷雾id -用于点击活动对应迷雾所属id
        public static void LoadMapFogData()
        {
            WorldMapFogData worldMap = AssetDatabase.LoadAssetAtPath<WorldMapFogData>("Assets/ResourcesAssets/World/mapdata/mapFogData.asset");
            UpdateMapFogData(worldMap);
        }

        public static void UpdateMapFogData(WorldMapFogData asset)
        {
            // 直接使用加载数据
            m_mapFogData = asset;
            m_mapFogTiles = new Dictionary<int, List<Vector2Int>>(m_mapFogData.mapFogRunDtas.Count);
            m_mapFogIdxToId = new Dictionary<int, int>(m_mapFogData.mapFogRunDtas.Count);
            // 解析数据
            for (int i = 0; i < m_mapFogData.mapFogRunDtas.Count; i++)
            {
                MapFogRunDta fog = m_mapFogData.mapFogRunDtas[i];
                // 解析idx - id 映射
                m_mapFogIdxToId[fog.indexFog] = fog.exploreId;
                // 解析该位置所属id
                Vector2Int fogIdx = new Vector2Int(fog.indexFog_x, fog.indexFog_y);
                if (!m_mapFogTiles.ContainsKey(fog.exploreId))
                {
                    m_mapFogTiles[fog.exploreId] = new List<Vector2Int>(9);
                }
                m_mapFogTiles[fog.exploreId].Add(fogIdx);
            }
        }

        public static int GetFogIdByIndex(int idx)
        {
            int id = 0;
            if (m_mapFogIdxToId != null && m_mapFogIdxToId.ContainsKey(idx))
            {
                id = m_mapFogIdxToId[idx];
            }
            return id;
        }

        static int fogLineNum = 180;
        static int mapFogLineNum = 120;
        static int mapFogSize = 10;

        public static int GetFogIdx(Vector3 mapPos)
        {
            int offsetIdx = ((fogLineNum - mapFogLineNum) / 2);
            int x = (int)mapPos.x / mapFogSize + offsetIdx;
            int y = (int)mapPos.z / mapFogSize + offsetIdx;
            int fogIdx = x + y * fogLineNum;

            return fogIdx;
        }

        public static List<Vector2Int> GetFogTilesById(int id)
        {
            List<Vector2Int> tiles = null;
            if (m_mapFogTiles != null && m_mapFogTiles.ContainsKey(id))
            {
                tiles = m_mapFogTiles[id];
            }
            return tiles;
        }
    }
}
